{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import cv2\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "#加载数据\n",
    "data = pd.read_csv('train.csv')\n",
    "x = data.loc[:,data.columns != 'label'].values.astype(np.float32)\n",
    "y = data['label'].values\n",
    "x = x / 255.0\n",
    "data = tf.data.Dataset.from_tensor_slices((x,y))\n",
    "data_loader = data.repeat().shuffle(5000).batch(128).prefetch(1)\n",
    "#熟悉数据\n",
    "for i in range(2):    \n",
    "    plt.imshow(np.reshape(x[i],[28,28]),cmap=\"gray\")\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#构造模型\n",
    "\n",
    "class network(tf.keras.Model):\n",
    "    def __init__(self):\n",
    "        super(network, self).__init__()\n",
    "        self.conv1 = tf.keras.layers.Conv2D(32,kernel_size=5,activation=tf.nn.relu)\n",
    "        self.maxpool1 =tf.keras.layers.MaxPool2D(2,strides=2)\n",
    "\n",
    "        self.conv2 = tf.keras.layers.Conv2D(64,kernel_size=3,activation=tf.nn.relu)\n",
    "        self.maxpool2 = tf.keras.layers.MaxPool2D(2,strides=2)\n",
    "\n",
    "        self.flatten = tf.keras.layers.Flatten()\n",
    "        self.fc1 = tf.keras.layers.Dense(1024)\n",
    "        self.dropout = tf.keras.layers.Dropout(rate=0.5)\n",
    "        self.out = tf.keras.layers.Dense(10)\n",
    "\n",
    "    def call(self,x,is_training=False):\n",
    "        x = tf.reshape(x,[-1,28,28,1])\n",
    "        x = self.conv1(x)\n",
    "        x = self.maxpool1(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.maxpool2(x)\n",
    "        x = self.flatten(x)\n",
    "        x = self.fc1(x)\n",
    "        x = self.dropout(x)\n",
    "        x = self.out(x)\n",
    "        if not is_training:\n",
    "            x = tf.nn.softmax(x)\n",
    "        return x\n",
    "conv = network()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#训练\n",
    "def cross_entropy_loss(x,y):   #定义损失函数\n",
    "    y = tf.cast(y,tf.int64)\n",
    "    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y,logits=x)\n",
    "    return tf.reduce_mean(loss)\n",
    "\n",
    "def accuracy(y_pred,y_true):    #计算模型精度\n",
    "    correct_pred = tf.equal(tf.argmax(y_pred,1),tf.cast(y_true,tf.int64))\n",
    "    return tf.reduce_mean(tf.cast(correct_pred,tf.float32))\n",
    "\n",
    "optimizer = tf.optimizers.SGD(0.01)\n",
    "\n",
    "def run_optimizer(x,y):    #训练\n",
    "    with tf.GradientTape() as g:\n",
    "        pred = conv(x,is_training=True)\n",
    "        loss = cross_entropy_loss(pred,y)\n",
    "    training_variable = conv.trainable_variables\n",
    "    gradient = g.gradient(loss,training_variable)\n",
    "    optimizer.apply_gradients(zip(gradient,training_variable))\n",
    "\n",
    "for i,(x_batch,y_batch) in enumerate(data_loader.take(1000),1):    #训练\n",
    "    run_optimizer(x_batch,y_batch)\n",
    "    if i%50==0:\n",
    "        pred = conv(x_batch)\n",
    "        acc = accuracy(pred,y_batch)\n",
    "        print(\"%f\"%(acc))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#训练完成后保存模型参数，避免下次以下时还要训练\n",
    "conv.save_weights('mannul_checkpoint')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#加载模型，这里可以将训练的代码注释掉了\n",
    "conv.load_weights('mannul_checkpoint')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#定义绘图函数\n",
    "Drawing = False  # 是否开始画图\n",
    "Start = (-1, -1)\n",
    "\n",
    "def mouse_event(event, x, y, flags, param):\n",
    "    global start, Drawing\n",
    "    # 左键按下：开始画图\n",
    "    if event == cv2.EVENT_LBUTTONDOWN:\n",
    "        Drawing = True\n",
    "        start = (x, y)\n",
    "    # 鼠标移动，画图\n",
    "    elif event == cv2.EVENT_MOUSEMOVE:\n",
    "        if Drawing:\n",
    "            cv2.circle(img, (x, y), 8, (random.randint(185,255)), -1)\n",
    "    # 左键释放：结束画图\n",
    "    elif event == cv2.EVENT_LBUTTONUP:\n",
    "        Drawing = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'mouse_event' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-10-c43b58f72b41>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mimg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m512\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m512\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0muint8\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnamedWindow\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'image'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mcv2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msetMouseCallback\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'image'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mmouse_event\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;32mwhile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'mouse_event' is not defined"
     ]
    }
   ],
   "source": [
    "img = np.zeros((512, 512, 1), np.uint8)\n",
    "cv2.namedWindow('image')\n",
    "cv2.setMouseCallback('image', mouse_event)\n",
    "\n",
    "while(True):\n",
    "    temp = img.copy()      #将temp送入训练好的模型中\n",
    "    a = temp[:400,:400]\n",
    "    cv2.imshow('a',cv2.resize(a,(28,28)))\n",
    "    temp = temp.astype(np.float32)\n",
    "    temp = cv2.resize(temp[:400,:400],(28,28))\n",
    "    temp = np.reshape(temp,[1,784])\n",
    "\n",
    "    pred = conv(temp, is_training=False)\n",
    "    b = np.argmax(pred.numpy())\n",
    "\n",
    "    cv2.imshow('image', img)\n",
    "    # 按下a撤销之前所画的图像，并打印预测值\n",
    "    if cv2.waitKey(1) == ord('a'):\n",
    "        img = np.zeros((512, 512, 1), np.uint8)\n",
    "\n",
    "        cv2.putText(img, str(\"pred:\"+str(b)), (40, 450), cv2.FONT_HERSHEY_COMPLEX, 2.0, (100, 200, 200), 2)\n",
    "    elif cv2.waitKey(1) == 27:\n",
    "        break"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
